package com.flow.framework.common.json;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
import com.flow.framework.common.datetime.CommonDateTimeFormatter;
import com.flow.framework.common.error.SystemErrorCode;
import com.flow.framework.common.exception.CheckedException;
import com.flow.framework.common.json.deserializer.ObjectToStringDeserializer;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;

/**
 * ObjectMapper holder
 *
 * @author luoguopiao
 * @version 0.0.1
 * @date 2022/1/2
 */
public class ObjectMapperHolder {

    public static ObjectMapper getInstance() {
        return Holder.OBJECT_MAPPER;
    }

    private static class Holder {
        private static final ObjectMapper OBJECT_MAPPER = getObjectMapper();

        private static ObjectMapper getObjectMapper() {
            try {
                // 初始化JavaTimeModule
                JavaTimeModule javaTimeModule = new JavaTimeModule();

                //处理LocalDateTime
                javaTimeModule.addSerializer(LocalDateTime.class,
                        new LocalDateTimeSerializer(CommonDateTimeFormatter.COMMON_DATETIME_FORMATTER));
                javaTimeModule.addDeserializer(LocalDateTime.class,
                        new LocalDateTimeDeserializer(CommonDateTimeFormatter.COMMON_DATETIME_FORMATTER));

                //处理LocalDate
                javaTimeModule.addSerializer(LocalDate.class,
                        new LocalDateSerializer(CommonDateTimeFormatter.COMMON_DATE_FORMATTER));
                javaTimeModule.addDeserializer(LocalDate.class,
                        new LocalDateDeserializer(CommonDateTimeFormatter.COMMON_DATE_FORMATTER));

                //处理LocalTime
                javaTimeModule.addSerializer(LocalTime.class,
                        new LocalTimeSerializer(CommonDateTimeFormatter.COMMON_TIME_FORMATTER));
                javaTimeModule.addDeserializer(LocalTime.class,
                        new LocalTimeDeserializer(CommonDateTimeFormatter.COMMON_TIME_FORMATTER));


                // 允许将任何json对象反序列化成对象中的字符串
                javaTimeModule.addDeserializer(String.class, new ObjectToStringDeserializer());

                ObjectMapper objectMapper = new ObjectMapper();
                //注册时间模块, 支持支持jsr310, 即新的时间类(java.time包下的时间类)
                objectMapper.registerModule(javaTimeModule);

                objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
                objectMapper.configure(DeserializationFeature.FAIL_ON_NUMBERS_FOR_ENUMS, true);
                objectMapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
                return objectMapper;
            } catch (Exception e) {
                throw new CheckedException(SystemErrorCode.SYSTEM_START_ERROR, "Initialize ObjectMapper failed.", e);
            }
        }
    }
}
